<template>
  <div class="particle-container">
    <div class="controls-panel">
      <el-select v-model="currentShape" placeholder="选择粒子形态" @change="changeParticleShape">
        <el-option label="立方体" value="cube"></el-option>
        <el-option label="长方体" value="cuboid"></el-option>
        <el-option label="球体" value="sphere"></el-option>
        <el-option label="锥体" value="cone"></el-option>
        <el-option label="飞机" value="airplane"></el-option>
        <el-option label="飞船" value="spaceship"></el-option>
      </el-select>
      
      <el-button @click="toggleAnimation" :type="isAnimating ? 'danger' : 'success'">
        {{ isAnimating ? '停止动画' : '开始动画' }}
      </el-button>
      
      <el-button @click="resetScene" type="primary">
        重置场景
      </el-button>
      
      <el-slider v-model="particleCount" :min="10" :max="500" :step="10" @change="updateParticleCount">
        <template #default>
          <span>粒子数量: {{ particleCount }}</span>
        </template>
      </el-slider>
    </div>
    <div ref="container" class="particle-canvas"></div>
  </div>
</template>

<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

export default {
  name: 'ParticleWorld',
  data() {
    return {
      currentShape: 'cube',
      isAnimating: true,
      particleCount: 100,
      particles: [],
      particleGroup: null
    };
  },
  mounted() {
    this.initThreeJS();
    window.addEventListener('resize', this.onWindowResize);
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.onWindowResize);
    if (this.animationFrameId) {
      cancelAnimationFrame(this.animationFrameId);
    }
    if (this.renderer) {
      this.renderer.dispose();
    }
  },
  methods: {
    initThreeJS() {
      // 初始化场景
      this.scene = new THREE.Scene();
      this.scene.background = new THREE.Color(0x000020);

      // 初始化相机
      this.camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      );
      this.camera.position.set(0, 0, 15);

      // 初始化渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.$refs.container.appendChild(this.renderer.domElement);

      // 添加控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;

      // 添加灯光
      this.addLights();

      // 创建粒子组
      this.particleGroup = new THREE.Group();
      this.scene.add(this.particleGroup);

      // 创建初始粒子
      this.createParticles();

      // 开始渲染循环
      this.animate();
    },

    addLights() {
      // 环境光
      const ambientLight = new THREE.AmbientLight(0x404040, 0.6);
      this.scene.add(ambientLight);

      // 方向光
      const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
      directionalLight.position.set(10, 10, 10);
      this.scene.add(directionalLight);

      // 点光源
      const pointLight = new THREE.PointLight(0xff6b6b, 1, 100);
      pointLight.position.set(-10, 5, -10);
      this.scene.add(pointLight);
    },

    createParticles() {
      // 清空现有粒子
      this.particleGroup.clear();
      this.particles = [];

      for (let i = 0; i < this.particleCount; i++) {
        const particle = this.createParticle();
        this.particleGroup.add(particle.mesh);
        this.particles.push(particle);
      }
    },

    createParticle() {
      let geometry;
      let material;
      const size = Math.random() * 0.3 + 0.1;

      switch (this.currentShape) {
        case 'cube':
          geometry = new THREE.BoxGeometry(size, size, size);
          break;
        case 'cuboid':
          geometry = new THREE.BoxGeometry(size, size * 1.5, size * 0.8);
          break;
        case 'sphere':
          geometry = new THREE.SphereGeometry(size, 16, 16);
          break;
        case 'cone':
          geometry = new THREE.ConeGeometry(size, size * 2, 8);
          break;
        case 'airplane':
          // 简化的飞机形状
          geometry = new THREE.ConeGeometry(size, size * 2, 3);
          break;
        case 'spaceship':
          // 简化的飞船形状
          geometry = new THREE.ConeGeometry(size, size * 1.5, 6);
          break;
        default:
          geometry = new THREE.BoxGeometry(size, size, size);
      }

      // 随机颜色
      const color = new THREE.Color(
        Math.random() * 0.5 + 0.5,
        Math.random() * 0.5 + 0.5,
        Math.random() * 0.5 + 0.5
      );

      material = new THREE.MeshPhongMaterial({
        color: color,
        shininess: 100,
        emissive: color.clone().multiplyScalar(0.2)
      });

      const mesh = new THREE.Mesh(geometry, material);

      // 随机位置和旋转
      mesh.position.set(
        (Math.random() - 0.5) * 10,
        (Math.random() - 0.5) * 10,
        (Math.random() - 0.5) * 10
      );

      mesh.rotation.set(
        Math.random() * Math.PI,
        Math.random() * Math.PI,
        Math.random() * Math.PI
      );

      return {
        mesh: mesh,
        velocity: new THREE.Vector3(
          (Math.random() - 0.5) * 0.02,
          (Math.random() - 0.5) * 0.02,
          (Math.random() - 0.5) * 0.02
        ),
        rotationSpeed: new THREE.Vector3(
          (Math.random() - 0.5) * 0.02,
          (Math.random() - 0.5) * 0.02,
          (Math.random() - 0.5) * 0.02
        )
      };
    },

    animate() {
      this.animationFrameId = requestAnimationFrame(this.animate);

      if (this.isAnimating) {
        this.updateParticles();
      }

      this.controls.update();
      this.renderer.render(this.scene, this.camera);
    },

    updateParticles() {
      this.particles.forEach(particle => {
        // 更新位置
        particle.mesh.position.add(particle.velocity);

        // 更新旋转
        particle.mesh.rotation.x += particle.rotationSpeed.x;
        particle.mesh.rotation.y += particle.rotationSpeed.y;
        particle.mesh.rotation.z += particle.rotationSpeed.z;

        // 边界检查
        const position = particle.mesh.position;
        if (Math.abs(position.x) > 5) particle.velocity.x *= -1;
        if (Math.abs(position.y) > 5) particle.velocity.y *= -1;
        if (Math.abs(position.z) > 5) particle.velocity.z *= -1;
      });
    },

    onWindowResize() {
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    },

    changeParticleShape() {
      this.createParticles();
    },

    toggleAnimation() {
      this.isAnimating = !this.isAnimating;
    },

    resetScene() {
      this.createParticles();
    },

    updateParticleCount() {
      this.createParticles();
    }
  }
};
</script>

<style scoped>
.particle-container {
  width: 100%;
  height: 100vh;
  margin: 0;
  padding: 0;
  overflow: hidden;
  position: relative;
}

.particle-canvas {
  width: 100%;
  height: 100%;
}

.controls-panel {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 15px;
  background: rgba(0, 0, 0, 0.7);
  padding: 20px;
  border-radius: 10px;
  backdrop-filter: blur(10px);
}

.controls-panel .el-select,
.controls-panel .el-button {
  width: 200px;
}

.controls-panel .el-slider {
  width: 200px;
}
</style>
